﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using RPSImporter.Infrastructure;
using RPSImporter.Services.Data;
using System.Globalization;
using RPSImporter.Infrastructure.Attributes;
using RPSImporter.Models.Settings;
using RPSImporter.Services;

namespace RPSImporter.Models
{
   [FileTypeName("HierarchyHours_FileType")]
   public class HoursHierarchy : ModelBase, IModel
   {
      public HoursHierarchy()
      {
         this.FileSettings = DatabaseSvc.Instance.Settings.HoursHierarchyFileSettings.First();
      }

      public HoursHierarchyFileSettings FileSettings { get; set; }

      public bool Import()
      {
         try
         {
            if (this.GetData(this.FileSettings.Year) != String.Empty
               && !this.DB.ht_hs.Any(h => h.an == Convert.ToInt32(this.GetData(this.FileSettings.Year))
                                       && h.luna == Convert.ToInt32(this.GetData(this.FileSettings.Month))))
            {
               ht_h hour = new ht_h();
               hour.an = this.GetData(this.FileSettings.Year) != String.Empty ?
                        Convert.ToInt32(this.GetData(this.FileSettings.Year)) : (int?)null;
               hour.luna = this.GetMonthNumber(this.GetData(this.FileSettings.Month));
               hour.hierarchy_id = this.GetData(this.FileSettings.HierarchyCode) != String.Empty ?
                                       (from h in this.DB.HIERARCHies
                                        where h.Code.ToString() == this.GetData(this.FileSettings.HierarchyCode)
                                        select h.HIERARCHY_ID).FirstOrDefault() : 0;
               //hour.medie_ore = 

               hour.ef_sub_tratament_fb_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentFBTotal);
               hour.ef_sub_tratament_fb_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentFBEfectiv);
               hour.ef_sub_tratament_f_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentFTotal);
               hour.ef_sub_tratament_f_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentFEfectiv);
               hour.ef_sub_tratament_b_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentBTotal);
               hour.ef_sub_tratament_b_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentBEfectiv);
               hour.ef_intern_fb_total_ore = this.GetDataAsDouble(this.FileSettings.InternFBTotal);
               hour.ef_intern_fb_efectiv = this.GetDataAsDouble(this.FileSettings.InternFBEfectiv);
               hour.ef_intern_f_total_ore = this.GetDataAsDouble(this.FileSettings.InternFTotal);
               hour.ef_intern_f_efectiv = this.GetDataAsDouble(this.FileSettings.InternFEfectiv);
               hour.ef_intern_b_total_ore = this.GetDataAsDouble(this.FileSettings.InternBTotal);
               hour.ef_intern_b_efectiv = this.GetDataAsDouble(this.FileSettings.InternBEfectiv);
               hour.ef_interimar_fb_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarFBTotal);
               hour.ef_interimar_fb_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarFBEfectiv);
               hour.ef_interimar_f_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarFTotal);
               hour.ef_interimar_f_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarFEfectiv);
               hour.ef_interimar_b_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarBTotal);
               hour.ef_interimar_b_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarBEfectiv);
               hour.ef_global_fb_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalFBTotal);
               hour.ef_global_fb_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalFBEfectiv);
               hour.ef_global_f_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalFTotal);
               hour.ef_global_f_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalFEfectiv);
               hour.ef_global_b_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalBTotal);
               hour.ef_global_b_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalBEfectiv);
               hour.ef_extern_fb_total_ore = this.GetDataAsDouble(this.FileSettings.ExternFBTotal);
               hour.ef_extern_fb_efectiv = this.GetDataAsDouble(this.FileSettings.ExternFBEfectiv);
               hour.ef_extern_f_total_ore = this.GetDataAsDouble(this.FileSettings.ExternFTotal);
               hour.ef_extern_f_efectiv = this.GetDataAsDouble(this.FileSettings.ExternFEfectiv);
               hour.ef_extern_b_total_ore = this.GetDataAsDouble(this.FileSettings.ExternBTotal);
               hour.ef_extern_b_efectiv = this.GetDataAsDouble(this.FileSettings.ExternBEfectiv);
               hour.ef_categorie_anexa_fb_total_ore = this.GetDataAsDouble(this.FileSettings.OtherFBTotal);
               hour.ef_categorie_anexa_fb_efectiv = this.GetDataAsDouble(this.FileSettings.OtherFBEfectiv);
               hour.ef_categorie_anexa_f_total_ore = this.GetDataAsDouble(this.FileSettings.OtherFTotal);
               hour.ef_categorie_anexa_f_efectiv = this.GetDataAsDouble(this.FileSettings.OtherFEfectiv);
               hour.ef_categorie_anexa_b_total_ore = this.GetDataAsDouble(this.FileSettings.OtherBTotal);
               hour.ef_categorie_anexa_b_efectiv = this.GetDataAsDouble(this.FileSettings.OtherBEfectiv);

               this.UpdateParents(hour);

               this.DB.ht_hs.InsertOnSubmit(hour);
               this.DB.SubmitChanges();
            }
            else
            {
               ht_h hour = this.DB.ht_hs.FirstOrDefault(h => h.an == Convert.ToInt32(this.GetData(this.FileSettings.Year))
                                                          && h.luna == Convert.ToInt32(this.GetData(this.FileSettings.Month)));
               hour.an = this.GetData(this.FileSettings.Year) != String.Empty ? Convert.ToInt32(this.GetData(this.FileSettings.Year)) : (int?)null;
               hour.luna = this.GetMonthNumber(this.GetData(this.FileSettings.Month));
               hour.hierarchy_id = this.GetData(this.FileSettings.HierarchyCode) != String.Empty ?
                                       (from h in this.DB.HIERARCHies
                                        where h.Code.ToString() == this.GetData(this.FileSettings.HierarchyCode)
                                        select h.HIERARCHY_ID).FirstOrDefault() : 0;
               hour.ef_sub_tratament_fb_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentFBTotal);
               hour.ef_sub_tratament_fb_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentFBEfectiv);
               hour.ef_sub_tratament_f_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentFTotal);
               hour.ef_sub_tratament_f_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentFEfectiv);
               hour.ef_sub_tratament_b_total_ore = this.GetDataAsDouble(this.FileSettings.SubTratamentBTotal);
               hour.ef_sub_tratament_b_efectiv = this.GetDataAsDouble(this.FileSettings.SubTratamentBEfectiv);
               hour.ef_intern_fb_total_ore = this.GetDataAsDouble(this.FileSettings.InternFBTotal);
               hour.ef_intern_fb_efectiv = this.GetDataAsDouble(this.FileSettings.InternFBEfectiv);
               hour.ef_intern_f_total_ore = this.GetDataAsDouble(this.FileSettings.InternFTotal);
               hour.ef_intern_f_efectiv = this.GetDataAsDouble(this.FileSettings.InternFEfectiv);
               hour.ef_intern_b_total_ore = this.GetDataAsDouble(this.FileSettings.InternBTotal);
               hour.ef_intern_b_efectiv = this.GetDataAsDouble(this.FileSettings.InternBEfectiv);
               hour.ef_interimar_fb_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarFBTotal);
               hour.ef_interimar_fb_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarFBEfectiv);
               hour.ef_interimar_f_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarFTotal);
               hour.ef_interimar_f_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarFEfectiv);
               hour.ef_interimar_b_total_ore = this.GetDataAsDouble(this.FileSettings.InterimarBTotal);
               hour.ef_interimar_b_efectiv = this.GetDataAsDouble(this.FileSettings.InterimarBEfectiv);
               hour.ef_global_fb_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalFBTotal);
               hour.ef_global_fb_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalFBEfectiv);
               hour.ef_global_f_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalFTotal);
               hour.ef_global_f_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalFEfectiv);
               hour.ef_global_b_total_ore = this.GetDataAsDouble(this.FileSettings.GlobalBTotal);
               hour.ef_global_b_efectiv = this.GetDataAsDouble(this.FileSettings.GlobalBEfectiv);
               hour.ef_extern_fb_total_ore = this.GetDataAsDouble(this.FileSettings.ExternFBTotal);
               hour.ef_extern_fb_efectiv = this.GetDataAsDouble(this.FileSettings.ExternFBEfectiv);
               hour.ef_extern_f_total_ore = this.GetDataAsDouble(this.FileSettings.ExternFTotal);
               hour.ef_extern_f_efectiv = this.GetDataAsDouble(this.FileSettings.ExternFEfectiv);
               hour.ef_extern_b_total_ore = this.GetDataAsDouble(this.FileSettings.ExternBTotal);
               hour.ef_extern_b_efectiv = this.GetDataAsDouble(this.FileSettings.ExternBEfectiv);
               hour.ef_categorie_anexa_fb_total_ore = this.GetDataAsDouble(this.FileSettings.OtherFBTotal);
               hour.ef_categorie_anexa_fb_efectiv = this.GetDataAsDouble(this.FileSettings.OtherFBEfectiv);
               hour.ef_categorie_anexa_f_total_ore = this.GetDataAsDouble(this.FileSettings.OtherFTotal);
               hour.ef_categorie_anexa_f_efectiv = this.GetDataAsDouble(this.FileSettings.OtherFEfectiv);
               hour.ef_categorie_anexa_b_total_ore = this.GetDataAsDouble(this.FileSettings.OtherBTotal);
               hour.ef_categorie_anexa_b_efectiv = this.GetDataAsDouble(this.FileSettings.OtherBEfectiv);

               this.UpdateParents(hour);

               this.DB.SubmitChanges();
            }
            return true;
         }
         catch (Exception ex)
         {
            this.Error = ex.Message;
            return false;
         }
      }

      private void UpdateParents(ht_h hour)
      {
         IList<ht_h> hierarchies = new List<ht_h>();
         Action<long> getAllParents = null;
         getAllParents = new Action<long>(
            id =>
            {
               long? parentID = this.DB.HIERARCHies.FirstOrDefault(h => h.HIERARCHY_ID == id).PARENT_ID;
               if (parentID != -1 && parentID != null)
               {
                  var hierarchy = this.DB.HIERARCHies.FirstOrDefault(h => h.PARENT_ID == id);
                  if (hierarchy != null)
                  {
                     var h_hour = this.DB.ht_hs.FirstOrDefault(h => h.hierarchy_id == hierarchy.HIERARCHY_ID);
                     hierarchies.Add(h_hour);
                  }
                  getAllParents(hierarchy.HIERARCHY_ID);
               }
            });

         getAllParents(hour.hierarchy_id);
         foreach (var item in hierarchies)
         {
            item.ef_sub_tratament_fb_total_ore_cumul += hour.ef_sub_tratament_fb_total_ore;
            item.ef_sub_tratament_fb_efectiv_cumul += hour.ef_sub_tratament_fb_efectiv;
            item.ef_sub_tratament_f_total_ore_cumul += hour.ef_sub_tratament_f_total_ore;
            item.ef_sub_tratament_f_efectiv_cumul += hour.ef_sub_tratament_f_efectiv;
            item.ef_sub_tratament_b_total_ore_cumul += hour.ef_sub_tratament_b_total_ore;
            item.ef_sub_tratament_b_efectiv_cumul += hour.ef_sub_tratament_b_efectiv;
            item.ef_intern_fb_total_ore_cumul += hour.ef_intern_fb_total_ore;
            item.ef_intern_fb_efectiv_cumul += hour.ef_intern_fb_efectiv;
            item.ef_intern_f_total_ore_cumul += hour.ef_intern_f_total_ore;
            item.ef_intern_f_efectiv_cumul += hour.ef_intern_f_efectiv;
            item.ef_intern_b_total_ore_cumul += hour.ef_intern_b_total_ore;
            item.ef_intern_b_efectiv_cumul += hour.ef_intern_b_efectiv;
            item.ef_interimar_fb_total_ore_cumul += hour.ef_interimar_fb_total_ore;
            item.ef_interimar_fb_efectiv_cumul += hour.ef_interimar_fb_efectiv;
            item.ef_interimar_f_total_ore_cumul += hour.ef_interimar_f_total_ore;
            item.ef_interimar_f_efectiv_cumul += hour.ef_interimar_f_efectiv;
            item.ef_interimar_b_total_ore_cumul += hour.ef_interimar_b_total_ore;
            item.ef_interimar_b_efectiv_cumul += hour.ef_interimar_b_efectiv;
            item.ef_global_fb_total_ore_cumul += hour.ef_global_fb_total_ore;
            item.ef_global_fb_efectiv_cumul += hour.ef_global_fb_efectiv;
            item.ef_global_f_total_ore_cumul += hour.ef_global_f_total_ore;
            item.ef_global_f_efectiv_cumul += hour.ef_global_f_efectiv;
            item.ef_global_b_total_ore_cumul += hour.ef_global_b_total_ore;
            item.ef_global_b_efectiv_cumul += hour.ef_global_b_efectiv;
            item.ef_extern_fb_total_ore_cumul += hour.ef_extern_fb_total_ore;
            item.ef_extern_fb_efectiv_cumul += hour.ef_extern_fb_efectiv;
            item.ef_extern_f_total_ore_cumul += hour.ef_extern_f_total_ore;
            item.ef_extern_f_efectiv_cumul += hour.ef_extern_f_efectiv;
            item.ef_extern_b_total_ore_cumul += hour.ef_extern_b_total_ore;
            item.ef_extern_b_efectiv_cumul += hour.ef_extern_b_efectiv;
            item.ef_categorie_anexa_fb_total_ore_cumul += hour.ef_categorie_anexa_fb_total_ore;
            item.ef_categorie_anexa_fb_efectiv_cumul += hour.ef_categorie_anexa_fb_efectiv;
            item.ef_categorie_anexa_f_total_ore_cumul += hour.ef_categorie_anexa_f_total_ore;
            item.ef_categorie_anexa_f_efectiv_cumul += hour.ef_categorie_anexa_f_efectiv;
            item.ef_categorie_anexa_b_total_ore_cumul += hour.ef_categorie_anexa_b_total_ore;
            item.ef_categorie_anexa_b_efectiv_cumul += hour.ef_categorie_anexa_b_efectiv;
         }
      }
   }
}